﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace FieldTools.Util;

public static partial class Extention
{
    #region 获取图片

    /// <summary>
    /// 根据图片路径生成图片base64
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static byte[] LoadImageByte(this string url)
    {
        if (string.IsNullOrEmpty(url))
        {
            return null;
        }
        try
        {
            Image img = url.LoadImageFromUrl();
            img = img.Compress(new Size(640, 480));
            Bitmap bmp = new Bitmap(img);
            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

            byte[] arr = new byte[ms.Length];
            ms.Position = 0;
            ms.Read(arr, 0, (int)ms.Length);
            ms.Close();

            return arr;
        }
        catch (Exception ex)
        {
            return null;
        }
    }

    /// <summary>
    /// 根据图片路径生成图片base64
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static async Task<byte[]> LoadImageByteAsync(this string url)
    {
        if (string.IsNullOrEmpty(url))
        {
            return null;
        }
        try
        {
            Image img = await url.LoadImageFromUrlAsync();
            img = img.Compress(new Size(640, 480));
            Bitmap bmp = new Bitmap(img);
            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

            byte[] arr = new byte[ms.Length];
            ms.Position = 0;
            ms.Read(arr, 0, (int)ms.Length);
            ms.Close();

            return arr;
        }
        catch (Exception ex)
        {
            return null;
        }
    }
    /// <summary>
    /// 根据图片路径生成图片base64
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static async Task<string> LoadImageBase64Async(this string url)
    {
        if (string.IsNullOrEmpty(url))
        {
            return string.Empty;
        }
        var bytes = await url.LoadImageByteAsync();
        if (bytes != null)
        {
            return Convert.ToBase64String(bytes);
        }
        return string.Empty;
    }
    public static string LoadImageBase64(this string url)
    {
        if (string.IsNullOrEmpty(url))
        {
            return null;
        }
        var bytes = url.LoadImageByte();
        if (bytes != null)
        {
            return Convert.ToBase64String(bytes);
        }
        return null;
    }
    //public static string LoadImageBase64(this string url, out string md5)
    //{
    //    if (url.IsNullOrEmpty())
    //    {
    //        md5 = null;
    //        return null;
    //    }
    //    md5 = string.Empty;
    //    try
    //    {
    //        Image img = url.LoadImageFromUrl();
    //        img = img.Compress(new Size(640, 480));
    //        Bitmap bmp = new Bitmap(img);
    //        MemoryStream ms = new MemoryStream();
    //        bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

    //        byte[] arr = new byte[ms.Length];
    //        ms.Position = 0;
    //        ms.Read(arr, 0, (int)ms.Length);
    //        md5 = ms.MD5Stream();
    //        ms.Close();
    //        return Convert.ToBase64String(arr);
    //    }
    //    catch (Exception ex)
    //    {
    //        return null;
    //    }
    //}
    /// <summary>
    /// 从文件获取图片
    /// </summary>
    /// <param name="fileName">文件名</param>
    /// <returns></returns>
    public static Image LoadImageFromFile(this string fileName)
    {
        return Image.FromFile(fileName);
    }

    //下载网络图片
    public static Image LoadImageFromUrl(this string url)
    {
        var mywebclient = new System.Net.WebClient();
        byte[] Bytes = mywebclient.DownloadData(url);
        using (MemoryStream ms = new(Bytes))
        {
            Image outputImg = Image.FromStream(ms);
            return outputImg;
        }
    }

    //下载网络图片
    public static async Task<Image> LoadImageFromUrlAsync(this string url)
    {
        var mywebclient = new System.Net.WebClient();
        Uri uri = new(url);
        byte[] Bytes = await mywebclient.DownloadDataTaskAsync(uri);
        using (MemoryStream ms = new(Bytes))
        {
            Image outputImg = Image.FromStream(ms);
            return outputImg;
        }
    }
    /// <summary>
    /// 从base64字符串读入图片
    /// </summary>
    /// <param name="base64">base64字符串</param>
    /// <returns></returns>
    public static Image LoadImageFromBase64(this string base64)
    {
        byte[] bytes = Convert.FromBase64String(base64);
        MemoryStream memStream = new MemoryStream(bytes);
        Image img = Image.FromStream(memStream);
        return img;
    }

    /// <summary>
    /// 从URL格式的Base64图片获取真正的图片
    /// 即去掉data:image/jpg;base64,这样的格式
    /// </summary>
    /// <param name="base64Url">图片Base64的URL形式</param>
    /// <returns></returns>
    public static Image LoadImageFromBase64Url(this string base64Url)
    {
        string base64 = GetBase64String(base64Url);
        return base64.LoadImageFromBase64();
    }

    /// <summary>
    /// 获取真正的图片base64数据
    /// 即去掉data:image/jpg;base64,这样的格式
    /// </summary>
    /// <param name="base64UrlStr">带前缀的base64图片字符串</param>
    /// <returns></returns>
    public static string GetBase64String(this string base64UrlStr)
    {
        string parttern = "^(data:image/.*?;base64,).*?$";

        var match = Regex.Match(base64UrlStr, parttern);
        if (match.Groups.Count > 1)
            base64UrlStr = base64UrlStr.Replace(match.Groups[1].ToString(), "");

        return base64UrlStr;
    }

    #endregion

    #region 压缩

    /// <summary>
    /// 压缩图片
    /// 注:等比压缩
    /// </summary>
    /// <param name="img">原图片</param>
    /// <param name="width">压缩后宽度</param>
    /// <returns></returns>
    public static Image Compress(this Image img, int width)
    {
        return Compress(img, width, (int)(((double)width) / img.Width * img.Height));
    }

    /// <summary>
    /// 压缩图片
    /// </summary>
    /// <param name="img">原图片</param>
    /// <param name="width">压缩后宽度</param>
    /// <param name="height">压缩后高度</param>
    /// <returns></returns>
    public static Image Compress(this Image img, int width, int height)
    {
        Bitmap bitmap = new Bitmap(img, width, height);
        return bitmap;
    }
    /// <summary>
    /// 图片压缩功能
    /// </summary>
    /// <param name="sourceImage">原图</param>
    /// <param name="targetSize">目标压缩尺寸</param>
    /// <returns></returns>
    public static Image Compress(this Image sourceImage, Size targetSize)
    {
        int targetWidth = targetSize.Width, targetHeight = targetSize.Height;  //图片转换的目标的尺寸；由于图片原有的比例问题，目标尺寸不等于最终的尺寸。
        int width; //图片最终的宽
        int height; //图片最终的高
        try
        {
            System.Drawing.Imaging.ImageFormat format = sourceImage.RawFormat;
            Bitmap targetPicture = new Bitmap(targetWidth, targetHeight);
            Graphics g = Graphics.FromImage(targetPicture);
            g.Clear(Color.White);
            //计算缩放图片的大小
            if (sourceImage.Width > targetWidth && sourceImage.Height <= targetHeight)
            {
                width = targetWidth;
                height = (width * sourceImage.Height) / sourceImage.Width;
            }
            else if (sourceImage.Width <= targetWidth && sourceImage.Height > targetHeight)
            {
                height = targetHeight;
                width = (height * sourceImage.Width) / sourceImage.Height;
            }
            else if (sourceImage.Width <= targetWidth && sourceImage.Height <= targetHeight)
            {
                width = sourceImage.Width;
                height = sourceImage.Height;
            }
            else
            {
                width = targetWidth;
                height = (width * sourceImage.Height) / sourceImage.Width;
                if (height > targetHeight)
                {
                    height = targetHeight;
                    width = (height * sourceImage.Width) / sourceImage.Height;
                }
            }
            g.DrawImage(sourceImage, (targetWidth - width) / 2, (targetHeight - height) / 2, width, height);
            sourceImage.Dispose();
            return targetPicture;
        }
        catch (Exception ex)
        {
        }
        return null;
    }

    #endregion

    #region 转换

    /// <summary>
    /// 将图片转为base64字符串
    /// 默认使用jpg格式
    /// </summary>
    /// <param name="img">图片对象</param>
    /// <returns></returns>
    public static string ToBase64String(this Image img)
    {
        return ToBase64String(img, ImageFormat.Jpeg);
    }

    /// <summary>
    /// 将图片转为base64字符串
    /// 使用指定格式
    /// </summary>
    /// <param name="img">图片对象</param>
    /// <param name="imageFormat">指定格式</param>
    /// <returns></returns>
    public static string ToBase64String(this Image img, ImageFormat imageFormat)
    {
        MemoryStream memStream = new MemoryStream();
        img.Save(memStream, imageFormat);
        byte[] bytes = memStream.ToArray();
        string base64 = Convert.ToBase64String(bytes);

        return base64;
    }

    /// <summary>
    /// 将图片转为base64字符串
    /// 默认使用jpg格式,并添加data:image/jpg;base64,前缀
    /// </summary>
    /// <param name="img">图片对象</param>
    /// <returns></returns>
    public static string ToBase64StringUrl(this Image img)
    {
        return "data:image/jpg;base64," + ToBase64String(img, ImageFormat.Jpeg);
    }

    /// <summary>
    /// 将图片转为base64字符串
    /// 使用指定格式,并添加data:image/jpg;base64,前缀
    /// </summary>
    /// <param name="img">图片对象</param>
    /// <param name="imageFormat">指定格式</param>
    /// <returns></returns>
    public static string ToBase64StringUrl(this Image img, ImageFormat imageFormat)
    {
        string base64 = ToBase64String(img, imageFormat);

        return $"data:image/{imageFormat.ToString().ToLower()};base64,{base64}";
    }

    #endregion

    /// <summary>
    /// 下载线上文件到本地(gif图片可以保持动画)
    /// </summary>
    /// <param name="url">下载文件链接</param>
    /// <param name="filename">保存到本地的地址</param>
    /// <returns></returns>
    public static void DownloadFile(this string url, string filename)
    {
        if (string.IsNullOrEmpty(url)) return;
        HttpWebRequest req = null;
        HttpWebResponse rep = null;
        Stream st = null;
        Stream so = null;
        try
        {
            req = (HttpWebRequest)WebRequest.Create(url);//请求网络资源

            req.UserAgent = "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Mobile Safari/537.36";

            rep = (HttpWebResponse)req.GetResponse();//返回Internet资源的响应
            long totalBytes = rep.ContentLength;//获取请求返回内容的长度
            st = rep.GetResponseStream();//读取服务器的响应资源，以IO流的形式进行读写
            so = new FileStream(filename, FileMode.Create);
            long totalDownloadedByte = 0;
            byte[] by = new byte[1024];
            int osize = st.Read(by, 0, (int)by.Length);
            while (osize > 0)
            {
                totalDownloadedByte = osize + totalDownloadedByte;
                so.Write(by, 0, osize);
                osize = st.Read(by, 0, (int)by.Length);//读取当前字节流的总长度
            }
            so.Flush();
        }
        catch (Exception ex) { ex.ToString(); }
        finally
        {
            if (so != null) { so.Close(); so.Dispose(); }
            if (st != null) { st.Close(); st.Dispose(); }
            if (rep != null) { rep.Close(); rep.Close(); }// rep.Dispose();
            if (req != null) { req.Abort(); }

        }
    }
}
